package storage

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"time"

	"demo2/config"

	"github.com/go-redis/redis/v8"
)

// Message 消息结构
type Message struct {
	ID        string    `json:"id"`
	SessionID string    `json:"sessionId"`
	Role      string    `json:"role"` // "user" 或 "assistant"
	Content   string    `json:"content"`
	Timestamp time.Time `json:"timestamp"`
}

// RedisStore Redis存储实现
type RedisStore struct {
	client *redis.Client
	config config.RedisConfig
}

// NewRedisStore 创建新的Redis存储
func NewRedisStore(cfg config.RedisConfig) *RedisStore {
	return &RedisStore{
		config: cfg,
	}
}

// Connect 连接到Redis
func (r *RedisStore) Connect() error {
	r.client = redis.NewClient(&redis.Options{
		Addr:     r.config.Addr,
		Password: r.config.Password,
		DB:       r.config.DB,
	})

	// 测试连接
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	_, err := r.client.Ping(ctx).Result()
	if err != nil {
		return fmt.Errorf("Redis连接失败: %v", err)
	}

	return nil
}

// Close 关闭Redis连接
func (r *RedisStore) Close() error {
	if r.client != nil {
		return r.client.Close()
	}
	return nil
}

// SaveMessage 保存消息
func (r *RedisStore) SaveMessage(ctx context.Context, message *Message) error {
	log.Printf("[REDIS-STORE] 💾 保存消息，会话ID: %s, 角色: %s, 消息ID: %s", message.SessionID, message.Role, message.ID)
	
	// 将消息序列化为JSON
	data, err := json.Marshal(message)
	if err != nil {
		log.Printf("[REDIS-STORE] ❌ 序列化消息失败: %v", err)
		return fmt.Errorf("序列化消息失败: %v", err)
	}

	// 使用有序集合存储消息，以时间戳作为分数
	key := fmt.Sprintf("chat:session:%s", message.SessionID)
	score := float64(message.Timestamp.Unix())

	log.Printf("[REDIS-STORE] 📤 写入Redis，键: %s, 分数: %f", key, score)
	err = r.client.ZAdd(ctx, key, &redis.Z{
		Score:  score,
		Member: string(data),
	}).Err()

	if err != nil {
		log.Printf("[REDIS-STORE] ❌ 保存消息到Redis失败: %v", err)
		return fmt.Errorf("保存消息失败: %v", err)
	}

	// 设置过期时间（7天）
	r.client.Expire(ctx, key, 7*24*time.Hour)
	log.Printf("[REDIS-STORE] ✅ 消息保存成功，设置7天过期时间")

	return nil
}

// GetMessages 获取会话的所有消息
func (r *RedisStore) GetMessages(ctx context.Context, sessionID string) ([]*Message, error) {
	key := fmt.Sprintf("chat:session:%s", sessionID)

	// 按时间戳顺序获取所有消息
	result, err := r.client.ZRange(ctx, key, 0, -1).Result()
	if err != nil {
		return nil, fmt.Errorf("获取消息失败: %v", err)
	}

	messages := make([]*Message, 0, len(result))
	for _, data := range result {
		var message Message
		if err := json.Unmarshal([]byte(data), &message); err != nil {
			continue // 跳过无法解析的消息
		}
		messages = append(messages, &message)
	}

	return messages, nil
}

// ClearMessages 清除会话的所有消息
func (r *RedisStore) ClearMessages(ctx context.Context, sessionID string) error {
	key := fmt.Sprintf("chat:session:%s", sessionID)
	err := r.client.Del(ctx, key).Err()
	if err != nil {
		return fmt.Errorf("清除消息失败: %v", err)
	}
	return nil
}

// GetRecentMessages 获取最近的N条消息
func (r *RedisStore) GetRecentMessages(ctx context.Context, sessionID string, limit int) ([]*Message, error) {
	log.Printf("[REDIS-STORE] 📚 获取最近消息，会话ID: %s, 限制数量: %d", sessionID, limit)
	
	key := fmt.Sprintf("chat:session:%s", sessionID)

	// 获取最近的消息（按分数倒序）
	log.Printf("[REDIS-STORE] 📤 从Redis查询，键: %s", key)
	result, err := r.client.ZRevRange(ctx, key, 0, int64(limit-1)).Result()
	if err != nil {
		log.Printf("[REDIS-STORE] ❌ 从Redis获取消息失败: %v", err)
		return nil, fmt.Errorf("获取最近消息失败: %v", err)
	}

	log.Printf("[REDIS-STORE] 📥 从Redis获取到 %d 条原始消息", len(result))

	messages := make([]*Message, 0, len(result))
	// 反转顺序，使其按时间正序排列
	for i := len(result) - 1; i >= 0; i-- {
		var message Message
		if err := json.Unmarshal([]byte(result[i]), &message); err != nil {
			log.Printf("[REDIS-STORE] ⚠️ 跳过无法解析的消息: %v", err)
			continue
		}
		messages = append(messages, &message)
	}

	log.Printf("[REDIS-STORE] ✅ 成功解析 %d 条消息", len(messages))
	return messages, nil
}
